#include "buffer.h"

Buffer* BufferCreate(int capacity) {
  Buffer* b = (Buffer *)malloc(sizeof(Buffer));
  b->capacity = capacity;
  b->offset   = 0;
  b->length   = 0;
  b->data = (char *)malloc(sizeof(char) * (capacity + 1));
  return b;
}

Buffer* BufferCreate2(const char* cmd, int length) {
  Buffer* b = (Buffer *)malloc(sizeof(Buffer));
  b->capacity = length;
  b->data = (char *)malloc(sizeof(char) * (length + 1));
  memcpy(b->data, cmd, length);
  b->data[length] = '\0';
  b->offset   = 0;
  b->length   = length;
  return b;
}

#include <stdio.h>

void BufferDestroy(void* data) {
  if (data) {
    Buffer* b = (Buffer *)data;
    if (b->data) {
      printf("buffer %p\n", b->data);
      free(b->data);
    }
    free(b);
  }
}

Buffer* BufferResize(Buffer* b, int capacity) {
  if (capacity <= 0) {
    b->capacity = b->capacity * 2;
  } else {
    b->capacity = capacity;
  }
  
  b->data = (char *)realloc(b->data, b->capacity + 1);

  return b;
}

int BufferCanContains(Buffer* b, int length) {
  return b->capacity - b->length >= length;
}

Buffer* BufferShift(Buffer* b) {
  if (b->offset == b->length) {
    b->offset = 0;
    b->length = 0;
  } else if (b->offset > 0) {
    b->length = b->length - b->offset;
    memmove(b->data, b->data + b->offset, b->length);
    b->offset = 0;
  }
  return b;
}

Buffer* BufferExpand(Buffer* b, int capacity) {
  BufferShift(b);
  if (capacity > b->capacity - b->length) {
    BufferResize(b, b->capacity + capacity - (b->capacity - b->length));
  }
  return b;
}

Buffer* BufferAppend(Buffer* b, const char* data, int length) {
  if (!BufferCanContains(b, length)) {
    BufferExpand(b, length);
  }
  memcpy(b->data + b->length, data, length);
  b->length += length;
  return b;
}

Buffer* BufferReset(Buffer* b) { 
  b->offset = 0;
  return b;
}

Buffer* BufferClear(Buffer* b) {
  b->offset = 0;
  b->length = 0;
  return b;
}

int BufferIsFull(Buffer* b) {
  return b->length == b->capacity;
}

